<?php

require_once 'Pipes/Controller/ActionMapper.php';
require_once 'Pipes/Model/Mapper.php';
require_once 'Pipes/View.php';
require_once 'PipesImpl/Uri.php';
require_once 'PipesImpl/Controller.php';
require_once 'PipesImpl/Route.php';

abstract class Pipes_Controller implements PipesImpl_Controller
{
    protected $config = null;
    protected $action = 'browse';
    protected $name = '';
    protected $view = null;
    protected $actionMapper = null;

    private $_data = array();
    protected $_route = null;
     
    public function __construct(PipesImpl_Config $config)
    {
        $explodedName = explode('_', get_class($this));
        $name = substr(array_pop($explodedName), 0, -10);
        
        $this->name = $name;
        
        $this->view = new Pipes_View($config, "Views/{$name}");
        
        $this->actionMapper = new Pipes_Controller_ActionMapper();
        $this->config = $config;
    }
    
    public function run(PipesImpl_Route $route) {
        $this->_route = $route;
        if (isset($route->action)) {
            $this->action = strtolower($route->action);
        }        
        $this->dispatch($route);
        
        if (!isset($this->title)) {
            $this->_set('title', ucwords("{$this->name} :: {$this->action}"));
        }
        
        $pageTypeClass = 'Pipes_Controller_PageType_Html';
        $finder = new Pipes_FileSystem_File_Finder($this);
        $finder->findByClass($pageTypeClass)->requireOnce();
        $pageType = new $pageTypeClass($this->config, $this);
        return $pageType->render($this->view->render($this->action));
    }
    
    protected function dispatch() {
        $mappedAction = $this->actionMapper->map($this->action);

        $callback = array($this, $mappedAction);
        if (is_callable($callback)) {
            $extras = $this->_route->extras;
            call_user_func_array($callback, $extras);
        }
    }
    
    /**
     *
     * Read-only version of setter that allows any value to be set on 
     * this controller.
     *
     * Generally used for setting internal variables to pass off to wrappers
     *
     */
    protected function _set($key, $value) {
        $this->_data[$key] = $value;
    }
    
    public function __set($key, $value) {
        throw new Pipes_Exception('Controller attributes are read-only');
    }

    public function __get($key) {
        return $this->_data[$key];
    }
    
    public function __isset($key) {
        return isset($this->_data[$key]);
    }
}

